<?php
/**
 * represents metadata about current foreach loop (tal:repeat).
 * Magic method used due to php case insensivity
 * @see http://wiki.zope.org/ZPT/RepeatVariable
 * @method string roman() repetition number as a lower-case roman numeral: "i", "ii", "iii", "iv", "v", etc.
 * @method string Roman() repetition number as a upper-case roman numeral: "i", "ii", "iii", "iv", "v", etc.
 * @todo  first - true for the first item in a group
 * @todo  last - true for the last item in a group
 */
class MicroTal_Repeat {
	/** @var array used to conver to roman numbers */
	static private $romanLookup__ = array(
	'M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400,
	'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40,
	'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1
	);
	/** @var integer Repetition number, starting from zero.*/
	public $index;
	/** @var integer Repetition number, starting from one.*/
	public $number;
	/** @var integer length of the sequence, which will be the total number of repetitions.	 */
	public $length;
	/**
	 * @param array $array array that will be interated
	 */
	function __construct(&$array) {
		if (!is_array($array)) {
			$array = array();
		}
		$this->length = count($array);
		$this->index = 0;
		$this->number = 1;
	}
	/**
	 * true for even-indexed repetitions (0, 2, 4, ...).
	 * @return boolean
	 */

	public function even() {
		return ($this->index % 2 == 0);
	}
	/**
	 * true for odd-indexed repetitions (1, 3, 5, ...).
	 * @return boolean
	 */
	public function odd() {
		return ($this->index % 2 == 1);
	}
	/**
	 * true for the starting repetition (index 0).
	 * @return boolean
	 */
	public function start() {
		return ($this->index == 0);
	}
	/**
	 * true for the ending, or final, repetition.
	 * @return boolean
	 */
	public function end() {
		return ($this->number == $this->length);
	}

	/**
	 * Call before moving to next element
	 */
	public function iterate() {
		$this->index++;
		$this->number++;
	}

	/**
	 * repetition number as a lower-case letter: "a" - "z", "aa" - "az", "ba" - "bz", ..., "za" - "zz", "aaa" - "aaz", and so forth.
	 * @return string
	 */
	private function letter__() {
		$tmp = $this->number;
		$result = '';
		while($tmp > 0) {
			$rest = ($tmp -1)% 26;
			$result = chr(ord('a')+$rest).$result;
			$tmp -= $rest;
			$tmp = (int)(floor($tmp/26.0));
		}
		return $result;
	}

	/**
	 * repetition number as a upper-case roman numeral: "i", "ii", "iii", "iv", "v", etc.
	 * @see http://www.go4expert.com/forums/showthread.php?t=4948
	 * @return string
	 */
	private function roman__() {
		$tmp = $this->number;
		$result = '';

		foreach(self::$romanLookup__ as $roman => $value) {
			$multiplier = (int)($tmp / $value);
			$result .= str_repeat($roman, $multiplier);
			$tmp %= $value;
		}
		return $result;
	}

	function  __call($name, $arguments) {
		switch($name) {
			case 'letter':
				return $this->letter__();
				break;
			case 'Letter':
				return strtoupper($this->letter__());
				break;
			case 'roman':
				return strtolower($this->roman__());
				break;
			case 'Roman':
				return $this->roman__();
				break;
		}
	}
}

